package classloader;

import sun.misc.Launcher;

/**
 * 在运行期，一个Java类是由该类的完全限定名（binary name）和用于加载该类的定义类加载器所共同决定的。
 * 如果同样名字（完全相同限定名）是由两个不同的加载器所加载，那么这些类就是不同的，即便.class文件字节码相同，并且从相同的位置加载亦如此。
 * 在oracle的hotspot，系统属性sun.boot.class.path如果修改错了，则运行会出错：因为Object要先初始化，但是现在path修改错了，找不到Object了
 * Error occurred during initialization of VM
 * java/lang/NoClassDeFoundError: java/lang/Object
 *
 */
public class MyTest23 {
    public static void main(String[] args) {
        System.out.println(System.getProperty("sun.boot.class.path"));//根加载器路径
        System.out.println(System.getProperty("java.ext.dirs"));//扩展类加载器路径
        System.out.println(System.getProperty("java.class.path"));//应用类加载器路径

/*
內建于JVM中的启动类加载器会加载java.lang.ClassLoader以及其他的Java平台类,
当JVM启动时，一块特殊的机器码会运行，它会加载扩展类加载器与系统类加载器,
这块特殊的机器码叫做启动类加载器(Bootstrap),
启动类加载器并不是Java类，而其他的加载器则都是Java类，
启动类加载器是特定于平台的机器指令，它负责开启整个加载过程。
所有类加载器(除了启动类加载器)都被实现为Java类。不过，总归要有一个组件来加载第一个Java类加载器，从而让整个加载过程能够顺利
进行下去，加载第一个纯Java类加载器 就是启动类加载器的职责。
启动类加载器还会负责加载供JRE正常运行所需要的基本组件，这包括java.util与java.lang包中的类等等。

 */

        System.out.println(ClassLoader.class.getClassLoader());
        //此处由于系统和扩展类加载器都是Launcher其内部静态类，但又都是非public的，
        // 所以不能直接获取他们的类加载器，方法就是通过获取他们的外部类加载器是谁？从而确当他们的类加载器。
        System.out.println(Launcher.class.getClassLoader());
        //扩展类加载器与系统类加载器也是有启动类加载器加载的
        System.out.println(Launcher.getLauncher());
        //Launcher是有启动类加载器加载的，所以其类包含的静态成员类，也是启动类加载器加载的

        System.out.println("---------------------");
        //下面的系统属性指定系统类加载器，默认是AppClassLoader
        System.out.println(System.getProperty("java.system.class.loader"));
        //System.getProperty("java.system.class.loader") 这个属性来指定系统类加载器，
        //可以使用"java.system.class.loader"，来使用我们自己的类加载器来指定系统类加载器,看如下设置，然后执行 classloader.MyTest23
        //Terminal: java -Djava.system.class.loader=classloader.MyTest16 classloader.MyTest23
        //另外使用 自定义加载来 做为 系统类加载器，需要给我们自定义的方法增加一个构造函数
//        public MyTest16(ClassLoader pareent) {
//            super(pareent)
//        }


        System.out.println(MyTest23.class.getClassLoader());
        System.out.println(MyTest16.class.getClassLoader());
        System.out.println(ClassLoader.getSystemClassLoader());
    }
}
